﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using SharpShare.Utilities;

namespace SharpShare.Collections {
    public class WeakDictionary<TKey, TValue> where TValue : class {
        private Dictionary<TKey, WeakReference<TValue>> _innerDictionary;
        private object _lock = new object();

        public WeakDictionary(IEqualityComparer<TKey> comparer = null) {
            if (comparer == null)
                comparer = EqualityComparer<TKey>.Default;

            _innerDictionary = new Dictionary<TKey, WeakReference<TValue>>(comparer);
        }

        public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) {
            lock (_lock) {
                TValue value = null;
                WeakReference<TValue> weakValue;
                bool create = false;

                if (_innerDictionary.TryGetValue(key, out weakValue)) {
                    value = weakValue.Target;
                    if (!weakValue.IsAlive) {
                        _innerDictionary.Remove(key);
                        create = true;
                    }
                } else {
                    create = true;
                }

                if (create) {
                    value = valueFactory(key);
                    _innerDictionary.Add(key, WeakReference<TValue>.Create(value));
                }

                return value;
            }
        }
    }
}
